#ifndef __COMPONENT_PILOT_H__
#define __COMPONENT_PILOT_H__

#include "Components/Component.hpp"
#include "Engine/MathUtils.hpp"
#include <memory>
#include "Engine/Vector3.hpp"
#include "Engine/Vector2.hpp"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct ComponentCreature;
    struct ComponentBody;

    struct ComponentPilot : public Component
    {
    public:
        ComponentCreature *componentCreature;

        std::shared_ptr<Vector2> walkOrder = nullptr;
        std::shared_ptr<Vector3> flyOrder = nullptr;
        std::shared_ptr<Vector3> swimOrder = nullptr;
        Vector2 turnOrder;
        float jumpOrder;

        // 不避开的物体
        ComponentBody *doNotAvoidBody = nullptr;

        int32_t stuckCount;
        std::shared_ptr<Vector3> lastStuckCheckPosition = nullptr;
        double aboveBelowTime = 0;
        double lastStuckCheckTime = 0;

        std::vector<ComponentBody*> nearbyBodies;
        double nextBodiesUpdateTime = 0;
        double nextUpdateTime = 0;

        Vector3 destination = FastVector3::Zero;

        float speed;
        float range;
        bool ignoreHeightDifference;
        bool raycastDestination;
        bool takeRisks;
        bool isStuck;

        /**
         * @brief 设置移动的目的地
         * @param theDestination 移动的目的地，若目的地是 Vector3(0,0,0) 则表示停止移动
         * @param theSpeed 移动的速度
         * @param theRange 移动的范围
         * @param theIgnoreHeightDifference 是否忽略移动的高度差
         * @param theRaycastDestination
         * @param theTakeRiskstheDoNotAvoidBody
         * @param 
        */
        void setDestination(const Vector3 &theDestination, float theSpeed, float theRange, bool theIgnoreHeightDifference, bool theRaycastDestination, bool theTakeRisks, ComponentBody *theDoNotAvoidBody);

        // 停止动物移动
        void stop();

        bool isTerrainSafeToGo(const Vector3& position, const Vector3 &direction);
        ComponentBody *findNearestBodyInFront(const Vector3& position, const Vector2 &direction);
        Vector3 avoidNearestBody(const Vector3 &position, const Vector3 &destination);

        virtual void update(float dt) override;
        virtual void load(const nlohmann::json &jsonData) override;
        virtual const std::string &getName() const override;
        static const std::string &GetName();
    };
}

#endif
